﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Zatify.WebUI.Infrastructure;
using Zatify.WebUI.Infrastructure.Absrtact;
using Zatify.Domain.Abstract;
using Zatify.WebUI.Areas.Admin.Models.Reports;
using Zatify.WebUI.Admin.Models;
using Zatify.Domain.Data;
using Zatify.WebUI.Infrastructure.Filters;
using Zatify.WebUI.Models;

namespace Zatify.WebUI.Areas.Admin.Controllers
{
    [ZatifyAdminAuthorizeAttribute]
    [Utils.MyRequireHttps]
    public class ReportsController : AdminBaseController
    {
        private const int PageSize = 25;

        private IZatifyRepository repository;

        protected override AdminModules AdminModule
        {
            get { return AdminModules.Reports; }
        }

        public ReportsController(IZatifyRepository repository, IZatifyAuthProvider authProvider)
        //: base(authProvider)
        {
            this.repository = repository;
        }

        public ActionResult Index()
        {
            return View();
        }

        #region REPORT FOR TEST Users

        public ActionResult Users(bool? activeUsers, int page = 1)
        {
            var filteredUsers = GetFilteredUsers(activeUsers);

            var model = new UsersStatusReportViewModel()
            {
                ActiveUsers = activeUsers,
                PagingInfo = new PagingInfo()
                     {
                         TotalItems = filteredUsers.Count(),
                         ItemsPerPage = PageSize,
                         CurrentPage = page,
                     },
                Users = filteredUsers.Skip((page - 1) * PageSize).Take(PageSize).ToList()
            };

            var pages = new List<SelectListItem>();

            for (int i = 1; i <= model.PagingInfo.TotalPages; i++)
                pages.Add(new SelectListItem() { Text = i.ToString(), Value = i.ToString(), Selected = (i == page) });

            ViewData["pagesCount"] = pages;

            var statuses = new List<SelectListItem>();
            statuses.Add(new SelectListItem() { Text = "All", Value = null, Selected = !activeUsers.HasValue });
            statuses.Add(new SelectListItem() { Text = "Active", Value = "true", Selected = (activeUsers.HasValue && activeUsers.Value) });
            statuses.Add(new SelectListItem() { Text = "Inactive", Value = "false", Selected = (activeUsers.HasValue && !activeUsers.Value) });
            ViewData["Statuses"] = statuses;

            ViewData["ReportType"] = ReportType.UserReport;

            return View(model);
        }

        public ActionResult UsersReport(bool? activeUsers, ReportExportType reportExportType)
        {
            var users = GetFilteredUsers(activeUsers);

            switch (reportExportType)
            {
                case ReportExportType.PDF:
                    return File(Zatify.Domain.Concrete.ZatifyReportGenerator.GenerateUsersReport(users), "application/pdf", "Report - Users In Status.pdf");
                case ReportExportType.Excel:
                    return View("Excel/UsersReport", users);
                case ReportExportType.Print:
                    return View("Print/UsersReport", users);
                default:
                    return RedirectToAction("Users", new { activeUsers = activeUsers });
            }
        }

        private List<User> GetFilteredUsers(bool? isActive)
        {
            var users = repository.Users.ToList();

            if (isActive.HasValue)
            {
                users = users.Where(p => p.IsActive == isActive).ToList();
            }

            return users;
        }

        #endregion

        #region REPORT FOR TEST SystemUsers

        public ActionResult SystemUsers(string role, bool? activeUsers, int page = 1)
        {
            var systemUsers = GetFilteredSystemUsers(role, activeUsers);

            var model = new SystemUsersReportViewModel()
            {
                Role = role,
                ActiveUsers = activeUsers,
                SystemUsers = systemUsers.Skip((page - 1) * PageSize).Take(PageSize).ToList(),
                PagingInfo = new PagingInfo()
                {
                    TotalItems = systemUsers.Count(),
                    ItemsPerPage = PageSize,
                    CurrentPage = page,
                }
            };

            var pages = new List<SelectListItem>();

            for (int i = 1; i <= model.PagingInfo.TotalPages; i++)
                pages.Add(new SelectListItem() { Text = i.ToString(), Value = i.ToString(), Selected = (i == page) });

            ViewData["pagesCount"] = pages;


            var statuses = new List<SelectListItem>();
            statuses.Add(new SelectListItem() { Text = "All", Value = null, Selected = !activeUsers.HasValue });
            statuses.Add(new SelectListItem() { Text = "Active", Value = "true", Selected = (activeUsers.HasValue && activeUsers.Value) });
            statuses.Add(new SelectListItem() { Text = "Inactive", Value = "false", Selected = (activeUsers.HasValue && !activeUsers.Value) });
            ViewData["Statuses"] = statuses;

            var roles = new List<SelectListItem>();
            roles.Add(new SelectListItem() { Text = "All", Value = null, Selected = String.IsNullOrWhiteSpace(role) });
            roles.Add(new SelectListItem() { Text = "Administraotor", Value = "ADMIN", Selected = (!String.IsNullOrWhiteSpace(role) && role == model.Role) });
            roles.Add(new SelectListItem() { Text = "User", Value = "USER", Selected = (!String.IsNullOrWhiteSpace(role) && role == model.Role) });
            ViewData["Roles"] = roles;

            ViewData["ReportType"] = ReportType.SystemUserReport;

            return View(model);
        }

        public ActionResult SystemUsersReport(string role, bool? activeUsers, ReportExportType reportExportType)
        {
            var systemUsers = GetFilteredSystemUsers(role, activeUsers);

            switch (reportExportType)
            {
                case ReportExportType.PDF:
                    return File(Zatify.Domain.Concrete.ZatifyReportGenerator.GenerateSystemUsersReport(systemUsers), "application/pdf", "Report - System Users.pdf");
                case ReportExportType.Excel:
                    return View("Excel/SystemUsersReport", systemUsers);
                case ReportExportType.Print:
                    return View("Print/SystemUsersReport", systemUsers);
                default:
                    return RedirectToAction("Users", new { activeUsers = activeUsers });
            }
        }

        private List<SystemUser> GetFilteredSystemUsers(string role, bool? isActive)
        {
            var systemUsers = repository.SystemUsers.ToList();

            if (!String.IsNullOrWhiteSpace(role) && role != "All")
            {
                systemUsers = systemUsers.Where(p => p.Role == role).ToList();
            }

            if (isActive.HasValue)
            {
                systemUsers = systemUsers.Where(p => p.IsActive == isActive).ToList();
            }

            return systemUsers;
        }

        #endregion

        #region REPORT User Referrer 

        public ActionResult UserReferrers(string sortOrder, DateTime? dateFrom, DateTime? dateTo, string referredByID, string referredID, int page = 1)
        {
            var filteredReferrers = GetFilteredUserReferrers(dateFrom, dateTo, referredByID, referredID);

            var model = new UserReferrerReportViewModel()
            {
                DateFrom = dateFrom,
                DateTo = dateTo,
                ReferredByID = referredByID,
                ReferredID = referredID,

                UserReferrers = SortUserReferreres(filteredReferrers.AsQueryable(), sortOrder).Skip((page - 1) * PageSize).Take(PageSize).ToList(),
                PagingInfo = new PagingInfo()
                {
                    TotalItems = filteredReferrers.Count(),
                    ItemsPerPage = PageSize,
                    CurrentPage = page,
                },

                SortOrderParam = sortOrder,

                IDSortParam = (sortOrder != UserReferrerReportSortParameter.IDAsc) ?
                                     UserReferrerReportSortParameter.IDAsc : UserReferrerReportSortParameter.IDDesc,

                ReferredByIDSortParam = (sortOrder != UserReferrerReportSortParameter.ReferredByIDAsc) ?
                                     UserReferrerReportSortParameter.ReferredByIDAsc : UserReferrerReportSortParameter.ReferredByIDDesc,

                ReferredIDSortParam = (sortOrder != UserReferrerReportSortParameter.ReferredIDAsc) ?
                                     UserReferrerReportSortParameter.ReferredIDAsc : UserReferrerReportSortParameter.ReferredIDDesc,

                ReferredIDUserTypeSortParam = (sortOrder != UserReferrerReportSortParameter.ReferredIDUserTypeAsc) ?
                                     UserReferrerReportSortParameter.ReferredIDUserTypeAsc : UserReferrerReportSortParameter.ReferredIDUserTypeDesc,

                DateSortParam = (sortOrder != UserReferrerReportSortParameter.DateAsc) ?
                                     UserReferrerReportSortParameter.DateAsc : UserReferrerReportSortParameter.DateDesc,

                NoSortParam = (sortOrder != UserReferrerReportSortParameter.NoAsc) ?
                                     UserReferrerReportSortParameter.NoAsc : UserReferrerReportSortParameter.NoDesc,

                TotalSortParam = (sortOrder != UserReferrerReportSortParameter.TotalAsc) ?
                                     UserReferrerReportSortParameter.TotalAsc : UserReferrerReportSortParameter.TotalDesc
            };

            var pages = new List<SelectListItem>();

            for (int i = 1; i <= model.PagingInfo.TotalPages; i++)
                pages.Add(new SelectListItem() { Text = i.ToString(), Value = i.ToString(), Selected = (i == page) });

            ViewData["pagesCount"] = pages;

            ViewData["ReportType"] = ReportType.UserReferrerReport;

            return View(model);
        }

        public ActionResult UserReferrersReport(DateTime? dateFrom, DateTime? dateTo, string referredByID, string referredID, ReportExportType reportExportType)
        {
            var filteredReferrers = GetFilteredUserReferrers(dateFrom, dateTo, referredByID, referredID);

            switch (reportExportType)
            {
                case ReportExportType.PDF:
                    return File(Zatify.Domain.Concrete.ZatifyReportGenerator.GenerateUserReferrerReport(filteredReferrers), "application/pdf", "User Referrer Report.pdf");
                case ReportExportType.Excel:
                    return View("Excel/UserReferrersReport", filteredReferrers);
                case ReportExportType.Print:
                    return View("Print/UserReferrersReport", filteredReferrers);
                default:
                    return RedirectToAction("UserReferrers", new { dateFrom = dateFrom, dateTo = dateTo, referredByID = referredByID, referredID = referredID });
            }
        }

        private List<Report_UserReferrer_Result> GetFilteredUserReferrers(DateTime? dateFrom, DateTime? dateTo, string referredByID, string referredID)
        {
            return repository.UserReferrerReport(dateFrom, dateTo,
                !String.IsNullOrWhiteSpace(referredByID) ? referredByID : null,
                !String.IsNullOrWhiteSpace(referredID) ? referredID : null);
        }

        private IQueryable<Report_UserReferrer_Result> SortUserReferreres(IQueryable<Report_UserReferrer_Result> userReferrer, string sortOrder)
        {
            switch (sortOrder)
            {
                case UserReferrerReportSortParameter.IDAsc:
                    return userReferrer.OrderBy(u => u.ID);
                case UserReferrerReportSortParameter.IDDesc:
                    return userReferrer.OrderByDescending(u => u.ID);

                case UserReferrerReportSortParameter.ReferredByIDAsc:
                    return userReferrer.OrderBy(u => u.Referred_by_ID);
                case UserReferrerReportSortParameter.ReferredByIDDesc:
                    return userReferrer.OrderByDescending(u => u.Referred_by_ID);

                case UserReferrerReportSortParameter.ReferredIDAsc:
                    return userReferrer.OrderBy(u => u.Referred_ID);
                case UserReferrerReportSortParameter.ReferredIDDesc:
                    return userReferrer.OrderByDescending(u => u.Referred_ID);

                case UserReferrerReportSortParameter.ReferredIDUserTypeAsc:
                    return userReferrer.OrderBy(u => u.Referred_ID_UserType);
                case UserReferrerReportSortParameter.ReferredIDUserTypeDesc:
                    return userReferrer.OrderByDescending(u => u.Referred_ID_UserType);

                case UserReferrerReportSortParameter.DateAsc:
                    return userReferrer.OrderBy(u => u.Date);
                case UserReferrerReportSortParameter.DateDesc:
                    return userReferrer.OrderByDescending(u => u.Date);

                case UserReferrerReportSortParameter.NoAsc:
                    return userReferrer.OrderBy(u => u.No);
                case UserReferrerReportSortParameter.NoDesc:
                    return userReferrer.OrderByDescending(u => u.No);

                case UserReferrerReportSortParameter.TotalAsc:
                    return userReferrer.OrderBy(u => u.Total);
                case UserReferrerReportSortParameter.TotalDesc:
                    return userReferrer.OrderByDescending(u => u.Total);

                default:
                    return userReferrer;
            }
        }

        #endregion
    }
}
